import type { Metadata } from 'next'; import Link from 'next/link'; import { notFound } from 'next/navigation'; import { PageHeader, Section, Note } from '@/components/ui/section'; import { EmptyState } from '@/components/ui/empty-state'; import { Freshness } from '@/components/ui/freshness'; import { Badge, ClaimBadge, StatusBadge } from '@/components/ui/badge'; import { SourceBadge } from '@/components/ui/source-badge'; import { EPI_METRIC_LABEL } from '@/lib/queries/epidemiology'; import { YEAR_MIN, yearApprovalCounts, yearApprovals, yearEpidemiology, yearLiterature, yearTopSponsors, yearTrialTotals, yearTrialsByCancer, yearTrialsByPhase, yearsWithData } from '@/lib/queries/year'; import { fmtDate, fmtInt, fmtPct, humanize, phaseLabel, truncate } from '@/lib/format'; export const revalidate = 3600; type Params = { year: string }; function parseYear(raw: string): number | null { if (!/^\d{4}$/.test(raw)) return null; const y = Number(raw); const max = new Date().getUTCFullYear(); return y >= YEAR_MIN && y <= max ? y : null; } export async function generateMetadata({ params }: { params: Promise }): Promise { const y = parseYear((await params).year); return y ? { title: `${y} in cancer`, description: `Oncology approvals, registered studies, research output and registry data of ${y}, from dated records in the index.`, alternates: { canonical: `/year/${y}` } } : { title: 'Year' }; } export default async function YearPage({ params }: { params: Promise }) { const year = parseYear((await params).year); if (year == null) notFound(); const [years, approvalCounts, approvals, phases, totals, byCancer, sponsors, lit, epi] = await Promise.all([yearsWithData(), yearApprovalCounts(year), yearApprovals(year, 60), yearTrialsByPhase(year), yearTrialTotals(year), yearTrialsByCancer(year, 12), yearTopSponsors(year, 10), yearLiterature(year, 15), yearEpidemiology(year)]); const current = new Date().getUTCFullYear(); const partial = year === current; const prev = years.find((y) => y < year); const next = [...years].reverse().find((y) => y > year); const totalApprovals = approvalCounts.reduce((s, r) => s + r.n, 0); return (
{partial ? {year} is still in progress: counts grow with each connector run and registries have not yet published {year} observations. : null}
{approvalCounts.length ? ( <>

{approvalCounts.map((r) => ( {r.authority} · {r.jurisdiction}: {fmtInt(r.n)} records / {fmtInt(r.drugs)} drugs ))}

    {approvals.map((a) => (
  • {fmtDate(a.approval_date)} {a.drug_name} {' '} {a.authority} · {a.jurisdiction} {' '} {a.approval_type ? {a.approval_type === 'ORIG' ? 'original application' : a.approval_type === 'SUPPL' ? 'supplement' : a.approval_type} : null}{' '} {a.accelerated ? accelerated : null}{' '} {' '} {a.cancer_slug ? ( {a.cancer_name} ) : a.tumor_agnostic ? ( tumor-agnostic ) : ( cancer not stated in this record )} {truncate(a.indication, 160)}
  • ))}

All {year} records with filters →

) : ( Approval records exist from the authorities ingested (FDA via openFDA, Health Canada, EMA); older decisions may be undated in the source. )}
{totals ? ( <>
{[ ['Studies', totals.total], ['Interventional', totals.interventional], ['Phase III', totals.phase3], ['Industry-led', totals.industry], ['With posted results', totals.with_results], ['Countries with sites', totals.countries], ].map(([k, v]) => (
{k}
{fmtInt(v as number)}
))}
{phases.map((p) => ( ))}
By phase (a study with two phases counts in both)
Phase Studies Interventional Industry share
{p.phase === 'NA' ? 'Not applicable / not stated' : phaseLabel(p.phase)} {fmtInt(p.n)} {fmtInt(p.interventional)} {fmtPct(p.n ? p.industry / p.n : 0, 0)}
{byCancer.map((c) => ( ))}
Top-level cancers by studies (descendants included)
Cancer Studies Phase III
{c.canonical_name} {fmtInt(c.trials)} {fmtInt(c.phase3)}
{sponsors.map((s) => ( ))}
Lead sponsors of interventional studies first posted in {year}
Lead sponsor Class Studies Phase III
{s.lead_sponsor} {s.lead_sponsor_class ? humanize(s.lead_sponsor_class) : '—'} {fmtInt(s.n)} {fmtInt(s.phase3)}

source: clinicaltrials · first_posted_date as posted

) : ( The ClinicalTrials.gov connector ingests oncology studies of every year; first-posted dates start in 1999 for most registrations. )}
); }